package com.hup.utils.selenium;

import com.hup.utils.commons.AssertApp;
import com.hup.utils.selenium.service.BrowserService;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.RemoteWebDriver;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;

/**
 * 页签对象类,实现基本的:句柄,页签,页面功能
 * @author hugan
 * @date 2020/3/22
 */
@Log4j2
public abstract class BaseWebPage<R> {

    /**
     * 浏览器刚打开时,无访问页面时的地址
     */
    public static final String DEFAULT_NULL_URL = "data:,";

    /**
     * 浏览器页签的句柄ID,未获取到时是null
     */
    @Getter
    private String tabHandle;

    public abstract String url();

    public abstract R parseData(WebDriver browser);

    public R switchToAndParseData(WebDriver browser) {
        testNewTab(browser);
        return parseData(browser);
    }

    /**
     * 用新页签打开网页,如果网页已打开过(历史句柄有效),则复用页签
     * @param browser 调用前要保证浏览器可用或旧的页签句柄有效,否则会耗时很长; {@link BrowserService#getBrowser()}
     */
    public void testNewTab(WebDriver browser) {
        if (tabHandle == null || !browser.getWindowHandles().contains(tabHandle)) {
            newTab(browser);
        } else {
            browser.switchTo().window(tabHandle);
        }
    }

    /**
     * 使用新页签打开网页,处理句柄逻辑;
     * 如果当前页签是空页,则使用当前页签打开;
     */
    public void newTab(WebDriver browser) {
        String currentUrl = browser.getCurrentUrl();
        if (DEFAULT_NULL_URL.equals(currentUrl)) {
            //如果是空页签,则使用当前页签打开网页
            browser.get(url());
            tabHandle = browser.getWindowHandle();
        } else {
            Set<String> before = browser.getWindowHandles();
            log.info("before={}", before);
            ((RemoteWebDriver) browser).executeScript("window.open('" + url() + "', '_blank')");
            Set<String> afters = browser.getWindowHandles();
            log.info("afters={}", afters);
            for (String after : afters) {
                if (!before.contains(after)) {
                    log.info("新tab={}", after);
                    browser.switchTo().window(after);
                    tabHandle = after;
                    log.debug("切换句柄到新tab");
                    break;
                }
            }
        }
        AssertApp.notNull(tabHandle, "获取页签句柄失败?");
    }

    /**
     * 关闭多余的页签;有可能全部页签都被关闭
     * @param webPages 以获取到句柄的页面
     * @return 浏览器是否被关闭(所有标签都关闭后,就会关闭浏览器)
     */
    public static boolean closeUselessTab(BrowserService browserService, ArrayList<? extends BaseWebPage> webPages) {
        WebDriver browser = browserService.getBrowser();
        Set<String> windowHandles = browser.getWindowHandles();
        Iterator<String> it = windowHandles.iterator();
        String validTab = null;
        W1:
        while (it.hasNext()) {
            String next = it.next();

            for (BaseWebPage page : webPages) {
                if (next.equals(page.tabHandle)) {
                    validTab = page.tabHandle;
                    continue W1;
                }
            }
            browser.switchTo().window(next);
            //log.info("关闭={}", browser.getTitle());
            browser.close();

        }
        boolean closed = browserService.closeBrowserIfNotTab(browser);
        if (!closed) {
            //最后需要切换会可用的句柄
            browser.switchTo().window(validTab);
        }
        return closed;
    }

}
